package org.jin.jinaicode.core;

import cn.hutool.json.JSONUtil;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.service.TokenStream;
import dev.langchain4j.service.tool.ToolExecution;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.jin.jinaicode.ai.AiCodeGeneratorService;
import org.jin.jinaicode.ai.AiCodeGeneratorServiceFactory;
import org.jin.jinaicode.ai.model.HtmlCodeResult;
import org.jin.jinaicode.ai.model.MultiFileCodeResult;
import org.jin.jinaicode.ai.model.message.AiResponseMessage;
import org.jin.jinaicode.ai.model.message.ToolExecutedMessage;
import org.jin.jinaicode.ai.model.message.ToolRequestMessage;
import org.jin.jinaicode.core.parser.CodeParserExecutor;
import org.jin.jinaicode.core.saver.CodeFileSaverExecutor;
import org.jin.jinaicode.exception.BusinessException;
import org.jin.jinaicode.exception.ErrorCode;
import org.jin.jinaicode.model.enums.CodeGenTypeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.View;
import reactor.core.publisher.Flux;

import java.io.File;

/**
 * 代码生成门面类，组合代码生成和保存
 */
@Slf4j
@Service
public class AiCodeGeneratorFacade {

    @Resource
    private AiCodeGeneratorServiceFactory aiCodeGeneratorServiceFactory;
    @Autowired
    private View error;


    /**
     * 通用流式处理方法
     * @param codeStream
     * @param codeGenTypeEnum
     * @param userMessage
     * @return
     */
    private Flux<String> processCodeStream(Flux<String> codeStream,CodeGenTypeEnum codeGenTypeEnum,String userMessage, Long appId) {
        // 定义一个字符串拼接器，用于当流式返回所有代码之后，再保存代码
        StringBuilder stringBuilder = new StringBuilder();
        return codeStream.doOnNext(chunk->{
            stringBuilder.append(chunk);
        }).doOnComplete(()->{
            try {
                String completeCode = stringBuilder.toString();

                // 检查是否包含代码内容，如果不包含则跳过代码解析和保存
                if (!containsCodeContent(completeCode, codeGenTypeEnum)) {
                    log.info("AI回复不包含代码内容，跳过代码解析和保存");
                    return;
                }

                Object parserResult = CodeParserExecutor.executeParser(completeCode, codeGenTypeEnum);

                File saveDir = CodeFileSaverExecutor.executeSaver(parserResult, codeGenTypeEnum, appId);
                log.info("代码生成成功，保存路径：{}", saveDir.getAbsolutePath());
            }catch (Exception e){
                log.error("代码处理失败", e);
                // 不抛出异常，避免影响正常对话
            }

        });
    }

    /**
     * 普通结构输出
     * @param userMessage
     * @param type
     * @return
     */
    public File generateAndSaveCode(String userMessage, CodeGenTypeEnum type, Long appId) {
        if(type==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "生成代码类型不能为空");
        }
        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory.getAiCodeGeneratorService(appId);
        switch (type) {
            case HTML:
                HtmlCodeResult htmlCodeResult = aiCodeGeneratorService.generateHTMLCode(userMessage);
                return CodeFileSaverExecutor.executeSaver(htmlCodeResult, CodeGenTypeEnum.HTML, appId);
            case MULTI_FILE:
                MultiFileCodeResult multiFileCodeResult = aiCodeGeneratorService.generateMultiFileCode(userMessage);
                return CodeFileSaverExecutor.executeSaver(multiFileCodeResult, CodeGenTypeEnum.MULTI_FILE, appId);
            default:
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "不支持生成代码类型");
        }
    }


    /**
     * 流失输出
     * @param userMessage
     * @param type
     * @return
     */
    public Flux<String> generateAndSaveCodeStream(String userMessage, CodeGenTypeEnum type, Long appId) {
        if(type==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "生成代码类型不能为空");
        }
        AiCodeGeneratorService aiCodeGeneratorService = aiCodeGeneratorServiceFactory.getAiCodeGeneratorService(appId,type);
        switch (type) {
            case HTML:
                Flux<String> htmlCodeStream = aiCodeGeneratorService.generateHTMLCodeStream(userMessage);
                return processCodeStream(htmlCodeStream, CodeGenTypeEnum.HTML, userMessage, appId);
            case MULTI_FILE:
                Flux<String> multiFileCodeStream = aiCodeGeneratorService.generateMultiFileCodeStream(userMessage);
                return processCodeStream(multiFileCodeStream, CodeGenTypeEnum.MULTI_FILE, userMessage, appId);
            case VUE_PROJECT:
                TokenStream codeStream = aiCodeGeneratorService.generateVueProjectCodeStream(appId,userMessage);
                return processTokenStream(codeStream);
            default:
                throw new BusinessException(ErrorCode.PARAMS_ERROR, "不支持生成代码类型");
        }
    }

    /**
     * 将 TokenStream 转换为 Flux<String>，并传递工具调用信息
     *
     * @param tokenStream TokenStream 对象
     * @return Flux<String> 流式响应
     */
    private Flux<String> processTokenStream(TokenStream tokenStream) {
        return Flux.create(sink -> {
            tokenStream.onPartialResponse((String partialResponse) -> {
                        AiResponseMessage aiResponseMessage = new AiResponseMessage(partialResponse);
                        sink.next(JSONUtil.toJsonStr(aiResponseMessage));
                    })
                    .onPartialToolExecutionRequest((index, toolExecutionRequest) -> {
                        ToolRequestMessage toolRequestMessage = new ToolRequestMessage(toolExecutionRequest);
                        sink.next(JSONUtil.toJsonStr(toolRequestMessage));
                    })
                    .onToolExecuted((ToolExecution toolExecution) -> {
                        ToolExecutedMessage toolExecutedMessage = new ToolExecutedMessage(toolExecution);
                        sink.next(JSONUtil.toJsonStr(toolExecutedMessage));
                    })
                    .onCompleteResponse((ChatResponse response) -> {
                        sink.complete();
                    })
                    .onError((Throwable error) -> {
                        error.printStackTrace();
                        sink.error(error);
                    })
                    .start();
        });
    }


//    /**
//     * 流式多文件
//     * @param userMessage
//     * @return
//     */
//    private Flux<String> generateAndSaveMultiFileCodeStream(String userMessage) {
//
//    }
//
//    /**
//     * 流式单文件HTML
//     * @param userMessage
//     * @return
//     */
//    private Flux<String> generateAndSaveHTMLCodeStream(String userMessage) {
//
//    }


//    /**
//     * 结构式多文件
//     * @param userMessage
//     * @return
//     */
//    private File generateAndSaveMultiFileCode(String userMessage) {
//
//    }
//
    /**
     * 检查AI回复是否包含代码内容
     * @param content AI回复内容
     * @param codeGenTypeEnum 代码生成类型
     * @return 是否包含代码内容
     */
    private boolean containsCodeContent(String content, CodeGenTypeEnum codeGenTypeEnum) {
        if (content == null || content.trim().isEmpty()) {
            return false;
        }

        switch (codeGenTypeEnum) {
            case HTML:
                // 检查是否包含HTML代码块或HTML标签
                return content.contains("```html") ||
                       content.contains("<!DOCTYPE") ||
                       content.contains("<html") ||
                       content.contains("<head") ||
                       content.contains("<body");

            case MULTI_FILE:
                // 检查是否包含任何代码块
                return content.contains("```html") ||
                       content.contains("```css") ||
                       content.contains("```js") ||
                       content.contains("```javascript");

            default:
                return false;
        }
    }

//    /**
//     * 结构式单文件HTML
//     * @param userMessage
//     * @return
//     */
//    private File generateAndSaveHTMLCode(String userMessage) {
//
//    }

}
